﻿/*
 * OpenDoPE Word Add-In
 * Copyright (C) 2010-2011  Plutext Pty Ltd
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 * 
 * For details, see http://www.gnu.org/licenses/gpl-2.0.html
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NLog;
using System.Reflection;
using Word = Microsoft.Office.Interop.Word;

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System.IO;
using System.Xml.Linq;

using Microsoft.Office.Tools.Word.Extensions; // for VSTOObject


namespace OpenDoPE_Wed
{
    class MacroManager
    {
        static Logger log = LogManager.GetLogger("OpenDoPE_Wed");


        /// <summary>
        /// XML markup cannot be inserted in the specified location.
        /// Whether by design or otherwise, Word won't let
        /// you insert XML which contains vbaProject.bin!
        /// So, have to save/close the document, inject macro, then re-open.
        /// </summary>
        public static void injectMacro()
        {
            //object newName = "foo2.docm";
            object oMissing = Missing.Value;
            object format = Word.WdSaveFormat.wdFormatXMLDocumentMacroEnabled;

            //Globals.ThisAddIn.Application.ActiveDocument.SaveAs(ref newName, ref format, ref oMissing, ref oMissing,
            //    ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
            //    ref oMissing, ref oMissing, ref oMissing, ref oMissing);


            Word.Document doc = Globals.ThisAddIn.Application.ActiveDocument;
            if (doc.HasVBProject)
            {
                log.Warn("Already has a VB project");
                Mbox.ShowSimpleMsgBoxInfo("Your document already contains macros. This only works if it doesn't.  So please remove them, then try again.");
                return;
            }

            // Remove existing task pane - should now happen automatically
            //Microsoft.Office.Tools.CustomTaskPane ctp = Globals.ThisAddIn.getTaskPane(false);
            //Globals.ThisAddIn.removeTaskPane(ctp);

            do
            {
                Mbox.ShowSimpleMsgBoxInfo("In the dialog which follows, please save as a Word Macro-Enabled Document (*.docm)");
                Word.Dialog dialog = Globals.ThisAddIn.Application.Dialogs[Word.WdWordDialog.wdDialogFileSaveAs];
                dialog.Show();
                doc = Globals.ThisAddIn.Application.ActiveDocument;

            } while ( !(doc.FullName.EndsWith(".docm")
                        && doc.SaveFormat==13) );

            //Mbox.ShowSimpleMsgBoxInfo("save format " + doc.SaveFormat);

            string docPath = doc.FullName;
            object saveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
            doc.Close(ref saveChanges, ref oMissing, ref oMissing);

            string dir = Assembly.GetExecutingAssembly().CodeBase;
            log.Debug("Locating help file relative to " + dir);
            dir = dir.Replace(@"file:///", string.Empty);
            int lastPost = dir.LastIndexOf("/");
            dir = dir.Substring(0, lastPost) + "/macro/";
            dir = dir.Replace("/", "\\");

            string projectFile = dir + "vbaProject.bin";
            string dataFile = dir + "vbaData.xml";
            string signatureFile = dir + "vbaProjectSignature.bin";


            //Use Open Xml SDK to process it.
            using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(docPath, true))
            {

                // Action - 

                VbaProjectPart vbaProjectPart = wordDoc.MainDocumentPart.AddNewPart<VbaProjectPart>();
                using (FileStream fileStream = File.Open(projectFile, FileMode.Open))
                    vbaProjectPart.FeedData(fileStream);

                VbaDataPart vbaDataPart = vbaProjectPart.AddNewPart<VbaDataPart>();
                using (FileStream fileStream = File.Open(dataFile, FileMode.Open))
                    vbaDataPart.FeedData(fileStream);

                ExtendedPart ep = vbaProjectPart.AddExtendedPart("http://schemas.microsoft.com/office/2006/relationships/vbaProjectSignature", "application/vnd.ms-office.vbaProjectSignature", "bin");
                using (FileStream fileStream = File.Open(signatureFile, FileMode.Open))
                    ep.FeedData(fileStream);

                wordDoc.MainDocumentPart.Document.Save();
                //Flush the contents of the package
                wordDoc.Package.Flush();


            }
/*
            //Reopen
            try
            {
                openDocument(docPath);

            }
            // TODO catch can't insert exception
            catch (Exception e)
            {
                // Test case: Abode_Building_Inspection_Agreement
                log.Error(e);
                System.Windows.Forms.MessageBox.Show("This document is protected, so its not possible to inject the macro. ");
                return;
                // TODO: copy/paste our content into a new document?
            }
 * */
            Mbox.ShowSimpleMsgBoxInfo("Done: if you open " + docPath + ", the interview macro will run.");
        }

        private static Word.Document openDocument(object fileName)
        {

            object omissing = System.Reflection.Missing.Value;
            object addToRecentFilesObj = false;

            Word.Document resultDoc = Globals.ThisAddIn.Application.Documents.Open(ref fileName, ref omissing, ref omissing, ref addToRecentFilesObj, ref omissing,
                                             ref omissing, ref omissing, ref omissing, ref omissing, ref omissing, ref omissing,
                                             ref omissing, ref omissing, ref omissing, ref omissing, ref omissing);
            resultDoc.Activate();

            return resultDoc;
        }


        /// <summary>
        /// XML markup cannot be inserted in the specified location.
        /// Whether by design or otherwise, Word won't let
        /// you insert XML which contains vbaProject.bin!
        /// </summary>
        //public static void injectMacroInMemory()
        // See rev 39 for code which attempted to do that.

        /*
                /// <summary>
                /// This approach works, provided you haven't password protected
                /// the macro with "Lock Project for Viewing".
                /// That's a problem.  And its a bit slow.
                /// </summary>
                public static void injectMacroViaOrganizerCopy()
                {
                    string dir = Assembly.GetExecutingAssembly().CodeBase;
                    log.Debug("Locating help file relative to " + dir);
                    dir = dir.Replace(@"file:///", string.Empty);
                    int lastPost = dir.LastIndexOf("/");
                    dir = dir.Substring(0, lastPost) + "/macro/";
                    dir = dir.Replace("/", "\\");

                    string fileName = dir + "MacroHost.docm";

                    string thisDocx = Globals.ThisAddIn.Application.ActiveDocument.FullName;

                    string[] items = { "UserFormOptions", "UserFormQuestion", "NewMacros", "AndX", "Category",
                                       "ConditionRefX", "ConditionsX", "ConditionValue", "ConditionX",
                                       "CustomXmlUtilities", "DataBinding", "Factory", "FalseX", "Fixedd",
                                       "Free", "Interviewer", "NotX", "OrX", "Parse", "Question", "Questionnaire",
                                       "RepeatHandler", "Response", "Section", "SectionInfo", "StringBuilder",
                                       "TagData", "TrueX", "XPath", "XPathRefX", "XPaths" };

                    try
                    {
                        foreach( string item in items) {
                            Globals.ThisAddIn.Application.OrganizerCopy(fileName, thisDocx, item,
                                Word.WdOrganizerObject.wdOrganizerObjectProjectItems);
                        }
                        Mbox.ShowSimpleMsgBoxInfo("Joy!");
                    }
                    catch (Exception e)
                    {
                        System.Windows.Forms.MessageBox.Show("Unable to open local Help file.  Please visit our help online at www.plutext.com");
                        log.Error("Unable to open '" + fileName);
                        log.Error(e.Message);
                        return;
                    }

                }
         */ 

    }
}
